package com.gds.common.wechat;

import com.alibaba.fastjson.JSONObject;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;


import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;

/****
 * 封装微信接口
 */
public class WechatUtils {
    private static final String getWechatUserUrl = "https://open.weixin.qq.com/connect/oauth2/authorize";
    private static final String getAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
    private static final String checkAccessTokenUrl = "https://api.weixin.qq.com/sns/auth";
    private static final String refreshAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token";
    private static final String getUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo";

    private static RestTemplate restTemplate = new RestTemplate();

    /****
     * todo 返回微信授权登录url
     * @param  appid    是	公众号的唯一标识
     * @param  redirect_uri    是	授权后重定向的回调链接地址， 请使用 urlEncode 对链接进行处理
     * @param  response_type    是	返回类型，请填写code
     * @param  scope    是	应用授权作用域，snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），snsapi_userinfo （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且， 即使在未关注的情况下，只要用户授权，也能获取其信息 ）
     * @param  state    否	重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值，最多128字节
     *
     * @throws IOException
     */
    public static String toWechantLogin(String appid, String redirect_uri, String response_type, String scope, String state) throws IOException {
        //#wechat_redirect	是	无论直接打开还是做页面302重定向时候，必须带此参数
        final String wechat_redirect = "#wechat_redirect";
        //拼接 登录 url
        Map<String, Object> param = new LinkedHashMap(5);
        param.put("appid", appid);
        param.put("redirect_uri", URLEncoder.encode(redirect_uri, "UTF-8"));
        param.put("response_type", response_type);
        param.put("scope", scope);
        param.put("state", state + wechat_redirect);
        return getUrl(getWechatUserUrl, param, "获取微信授权页面路径");

    }

    /***
     * todo  获取微信 access_token
     *@param appid    是	公众号的唯一标识
     *@param secret    是	公众号的appsecret
     *@param code    是	填写第一步获取的code参数
     *@param grant_type    是	填写为authorization_code
     * @return
     */
    public static AccessTokenWechatHttpResult getAccessToken(String appid, String secret, String code, String grant_type) {
        Map<String, Object> param = new LinkedHashMap(4);
        param.put("appid", appid);
        param.put("secret", secret);
        param.put("code", code);
        param.put("grant_type", grant_type);
        String url = getUrl(getAccessTokenUrl, param, "微信网页授权access_token");
        String result = restTemplate.postForObject(url, null, String.class);
        System.out.println("请求微信网页授权access_token返回--" + result);
        AccessTokenWechatHttpResult accessToken = JSONObject.parseObject(result, AccessTokenWechatHttpResult.class);
        if (StringUtils.isEmpty(accessToken.getErrcode())) {
            accessToken.setCode(200);
        } else {
            accessToken.setCode(accessToken.getErrcode());
        }
        return accessToken;
    }


    /***
     * todo 刷新access_token（如果需要）
     * @param appid    是	公众号的唯一标识
     * @param grant_type    是	填写为refresh_token
     * @param refresh_token    是	填写通过access_token获取到的refresh_token参数
     */
    public static AccessTokenWechatHttpResult toRefreshToken(String appid, String grant_type, String refresh_token) {
        Map<String, Object> param = new LinkedHashMap(4);
        param.put("appid", appid);
        param.put("grant_type", grant_type);
        param.put("refresh_token", refresh_token);
        String url = getUrl(refreshAccessTokenUrl, param, "微信access_token刷新");
        String result = restTemplate.postForObject(url, null, String.class);
        System.out.println("请求微信access_token刷新返回--" + result);
        AccessTokenWechatHttpResult accessToken = JSONObject.parseObject(result, AccessTokenWechatHttpResult.class);
        if (StringUtils.isEmpty(accessToken.getErrcode())) {
            accessToken.setCode(200);
        } else {
            accessToken.setCode(accessToken.getErrcode());
        }
        return accessToken;
    }

    /***
     * todo 获取用户信息
     * @param  access_token    网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同
     * @param  openid    用户的唯一标识
     * @param  lang    返回国家地区语言版本，zh_CN 简体，zh_TW 繁体，en 英语
     *
     * @return
     */
    public static UserInfoWechatHttpResult userInfo(String access_token, String openid, String lang) throws UnsupportedEncodingException {
        Map<String, Object> param = new LinkedHashMap(4);
        param.put("access_token", access_token);
        param.put("openid", openid);
        param.put("lang", lang);
        String url = getUrl(getUserInfoUrl, param, "微信获取用户信息");
        String result = restTemplate.postForObject(url, null, String.class);
        result =new String(result.getBytes("ISO-8859-1"), "UTF-8");
        System.out.println("请求微信获取用户信息返回--" + result);
        UserInfoWechatHttpResult userInfo = JSONObject.parseObject(result, UserInfoWechatHttpResult.class);
        if (StringUtils.isEmpty(userInfo.getErrcode())) {
            userInfo.setCode(200);
        } else {
            userInfo.setCode(userInfo.getErrcode());
        }
        return userInfo;
    }

    /****
     * todo 查看 access_token是否有效
     * @param access_token    网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同
     * @param openid    用户的唯一标识
     */
    public static Boolean checkAccessToken(String access_token, String openid) {
        boolean   flag =false;
        Map<String, Object> param = new LinkedHashMap(4);
        param.put("access_token", access_token);
        param.put("openid", openid);
        String url = getUrl(checkAccessTokenUrl, param, "微信access_token是否放过期");
        String result = restTemplate.postForObject(url, null, String.class);
        System.out.println("请求微信access_token是否放过期返回--" + result);
        WechatHttpResult wechatHttpResult = JSONObject.parseObject(result, WechatHttpResult.class);
        if (0 == wechatHttpResult.getErrcode()) {
            flag =true;
        }
        return  flag;

    }


    /***
     * 拼接 url 并打印控制台
     * @param uri  请求接口路径
     * @param params 参数
     * @param tip  接口名称
     * @return 拼接好的 url;
     */
    private static String getUrl(String uri, Map<String, Object> params, String tip) {
        tip = "请求[" + tip + "]---:";
        if (StringUtils.isEmpty(uri)) {
            System.out.println(tip);
            return null;
        }
        if (CollectionUtils.isEmpty(params)) {
            System.out.println(tip + uri);
            return uri;
        }
        StringBuilder builder = new StringBuilder(uri);
        Integer i = 0;
        for (Map.Entry<String, Object> entry : params.entrySet()) {

            if (i == 0) {
                builder.append("?" + entry.getKey() + "=" + entry.getValue());
            } else {
                builder.append("&" + entry.getKey() + "=" + entry.getValue());
            }
            i++;
        }
        i = null;
        System.out.println(tip + builder.toString());
        return builder.toString();
    }
}
